﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using CommerceML.Version205;
using IBS;
using EdexApiClient;

namespace CommerceML2IBS
{
    public class IntegrationContext //: StringEditor
    {
        public delegate void ProcessedDocumentHandler(object sender, DocumentEventArgs e);
        public event ProcessedDocumentHandler ProcessedDocument;

        private string IbsConnectionString { get; set; }
        private IbsDataContext db { get; set; }

        public IntegrationContext(string IbsConnectionString)
        {
            this.IbsConnectionString = IbsConnectionString;
            this.db = new IbsDataContext(this.IbsConnectionString);
        }

        public void Process(string xmlData)
        {
            this.Process(xmlData, null);
        }

        public void Process(string xmlData, SaleOrder defaultDocument)
        {
            var data = this.GetCommerceML(xmlData);

            if (data.Items == null)
                return;

            data.Items.ToList().ForEach(r =>
            {
                if (r is Документ)
                    this.ProcessDocument((Документ)r, defaultDocument);
                if (r is Каталог)
                    this.ProcessCatalog((Каталог)r);
                if (r is ПакетПредложений)
                    this.ProcessPackage((ПакетПредложений)r);
            });
        }

        private void ProcessDocument(Документ entity, SaleOrder defaultDocument)
        {
            var document = new IBS.SaleOrder();
            document.OUTER_KEY = Guid.Parse(entity.Ид);
            document.DOC_DATE = entity.Дата;
            document.DOC_NUMBER = entity.Номер;
            document.TOTAL_AMOUNT = entity.Сумма;
            document.LINECOUNT = entity.Товары.Count();
            document.NOTE = String.IsNullOrEmpty(entity.Комментарий) ? String.Empty : entity.Комментарий;
            document.TAX_AMOUNT = entity.Налоги.Sum(r => r.Сумма);
            
            /// Получатель
            if (entity.Контрагенты.Any(r => r.Роль == РольТип.Покупатель))
            {
                var store = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Покупатель).Склад;
                document.LOCATION_KEY = int.Parse(store.Ид);
            }
            else
            {
                throw new Exception("Не указан Покупатель");
            }
            /// Поставщик
            if (entity.Контрагенты.Any(r => r.Роль == РольТип.Продавец))
            {
                var supplier = entity.Контрагенты.SingleOrDefault(r => r.Роль == РольТип.Продавец);
                //document.SupplierId = db.GetSupplierByGuid(Guid.Parse(supplier.Ид)).ID_Record;
                document.COMPANY_KEY = int.Parse(supplier.Ид);
            }
            else
            {
                throw new Exception("Не указан поставщик");
            }
            /// Позиции
            /// 
            document.SaleOrderItems = entity.Товары.Select((r, i) =>
            {
                var rate = decimal.Parse(System.Text.RegularExpressions.Regex.Match(r.СтавкиНалогов.FirstOrDefault().Ставка, @"\d+").Value);

                if (rate > 1)
                    rate = rate / 100;

                var item = new IBS.SaleOrderLine();
                item.ITEM_KEY = long.Parse(r.Ид);
                item.PRICE = r.ЦенаЗаЕдиницу;
                item.ACTUAL_PRICE = 0; //подставляется в процедуре
                item.QUANTITY = r.Количество;
                item.TOTAL = r.Сумма;
                item.TAX_TOTAL = r.Налоги.Sum(n => n.Сумма);
                item.TAX_RATE = rate;
                item.ORDER_NUM = i;

                //item.DISCOUNT = r.
                //item.TOTAL = r.

                return item;
            }).ToList();

            var doc_id = db.SaveSaleOrder(document);

            //сообщение о несоответствии цен
            /*if (doc_id != 0)
            {
                var orders = db.GetSaleOrderMsg(doc_id).ToList();
                //var msg = String.Empty;
                if (orders.Count > 0)
                {
                    StringBuilder resultString = new StringBuilder();
                    //msg = String.Format("{0}ID Товара{0}Цена в документе{0}Цена в справочнике{0}Цена, отправленная на АЗС{1}", "     ", Environment.NewLine);
                    resultString.Append(String.Format("{0}ID Товара\tЦена в документе\tЦена в справочнике\tЦена, отправленная на АЗС{1}", "     ", Environment.NewLine));                    
                    orders.ForEach(r =>
                        {
                            resultString.Append(String.Concat(GetFormattedString(r.ITEM_KEY.ToString(), 14, " ", false), "\t\t"));
                            resultString.Append(String.Concat(GetFormattedString(r.PRICE.ToString(), 16, " ", false), "\t\t"));
                            resultString.Append(String.Concat(GetFormattedString(r.ACTUAL_PRICE.ToString(), 18, " ", false), "\t\t"));
                            if (r.PRICE < r.ACTUAL_PRICE)
                            {
                                resultString.Append(String.Concat(GetFormattedString(r.PRICE.ToString(), 25, " ", false), Environment.NewLine));
                            }
                            else
                            {
                                resultString.Append(String.Concat(GetFormattedString(r.ACTUAL_PRICE.ToString(), 25, " ", false), Environment.NewLine));
                            }
                           // msg += String.Format("ID = {0} \tЦена в документе = {1} \tЦена в справочнике = {2} \tОтрпавлена на АЗС = {3}\n", r.ITEM_KEY, r.PRICE, r.ACTUAL_PRICE);
                        }
                       
                    );
                    
                    var subject = String.Format("Предупреждение о расхождении цены по документу № {0}", orders.First().DOC_NUMBER);
                    var body = String.Format(@"Контрагент: {1} ({2}){0}
Документ: {3} от {4} {0}АЗС: {6} - {7} ({5}) {0}

Сумма накладной поставщика: {8} {0}
Сумма накладной после подстановки из справочника: {9} 
Сумма, отправленная на станцию: {10} {0}{0}

{11}", 
                                                    string.Empty,                                  //0
                                                    orders.First().SUPNAME,                               //1
                                                    orders.First().COMPANY_KEY,                           //2
                                                    orders.First().DOC_NUMBER,                            //3
                                                    orders.First().DOC_DATE.ToString("dd.MM.yyyy"),       //4
                                                    orders.First().LOCATION_KEY,                          //5
                                                    orders.First().RCCODE,                                //6
                                                    orders.First().SITENAME,                              //7
                                                    orders.First().TOTAL,                                 //8
                                                    orders.First().TOTAL_ACTUAL,                          //9
                                                    orders.First().TOTAL < orders.First().TOTAL_ACTUAL ? orders.First().TOTAL : orders.First().TOTAL_ACTUAL, //10
                                                    resultString.ToString());                             //11
                    
                    var managers = db.GetManagerInfo(orders.First().COMPANY_KEY).ToList();
                        
                    managers.ForEach(r =>
                    {                        
                       db.SendMail("HelpDeskDS@tnk-bp.com", r.EMAIL, subject, body);
                    });

                    var siteEmail = orders.First().RCCODE + "m@mos.tnk-bp.ru";
                    db.SendMail("HelpDeskDS@tnk-bp.com", siteEmail, subject, body);                   
                }
            }*/

            if (ProcessedDocument != null)
            {
                ProcessedDocument(this, new DocumentEventArgs
                {
                    Id = entity.Ид,
                    DocumentNumber = entity.Номер,
                    IncomingNumber = doc_id.ToString()
                });
            }

        }
        
        private void ProcessCatalog(Каталог entity) { }

        private void ProcessPackage(ПакетПредложений entity) { }

        private CommerceML.Version205.КоммерческаяИнформация LoadCommerceML(string path)
        {
            // Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
            settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
            // Create the XmlReader object.
            XmlReader reader = XmlReader.Create(path, settings);
            XmlSerializer serializer = new XmlSerializer(typeof(CommerceML.Version205.КоммерческаяИнформация));
            var sd = (CommerceML.Version205.КоммерческаяИнформация)serializer.Deserialize(reader);
            reader.Close();
            return sd;
        }

        public CommerceML.Version205.КоммерческаяИнформация GetCommerceML(string xmlData)
        {
            //using (var reader = System.Xml.XmlReader.Create(uri))
            using (var reader = System.Xml.XmlReader.Create(new System.IO.StringReader(xmlData)))
            {
                var serializer
                    = new System.Xml.Serialization.XmlSerializer(typeof(CommerceML.Version205.КоммерческаяИнформация));
                return (CommerceML.Version205.КоммерческаяИнформация)serializer.Deserialize(reader);
            }
        }

        // Display any warnings or errors.
        private static void ValidationCallBack(object sender, ValidationEventArgs args)
        {
            if (args.Severity == XmlSeverityType.Warning)
                Console.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
            else
                Console.WriteLine("\tValidation error: " + args.Message);
        }

        public class DocumentEventArgs
        {
            public string Id { get; set; }
            public string DocumentNumber { get; set; }
            public string IncomingNumber { get; set; }
        }
    }
}
